package com.sunlands.deskmate.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import redis.clients.jedis.JedisCommands;
import java.util.Arrays;
import static com.sunlands.deskmate.config.RedisConfig.PREFIX;

/**
 * 防重的方式是根据键名在redis里写一个值, 如果值已经存在则说明重复
 * 应该强制设定expire, 否则redis存储数据会越来越多
 *
 * @author liude
 * @author anjunling@sunlands.com
 */
@SuppressWarnings("SameParameterValue")
@Component
@Slf4j
public class Idempotent {

    /**
     * 防重检测
     *
     * @param parts 拼接起来作为键名
     * @return 是否通过防重检测
     */
    public boolean idempotentCheck(String... parts) {
        boolean result = idempotentCheck(3600, parts);

        log.debug("idempotentCheck, parts={}, result={}", Arrays.asList(parts), result);
        
        return result;
    }


    private boolean idempotentCheck(long expireInSeconds, String... strs) {
        //维持时间3600秒是不是太长了? //TODO
        String key = idempotentKey(strs);

        String result = redisTemplate.execute((RedisCallback<String>) connection -> {
            JedisCommands commands = (JedisCommands) connection.getNativeConnection();
            return commands.set(key, "1", "NX", "EX", expireInSeconds);
        });
        return !StringUtils.isEmpty(result);
    }

    private String idempotentKey(String... strs) {
        Assert.notEmpty(strs, "args invalid");

        return String.format(PREFIX + ":msg-server:idempotent:idempotent_%s", String.join("_", strs));
    }

    private final RedisTemplate<String, String> redisTemplate;

    public Idempotent(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
}
